/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package wechat

import (
	"gitee.com/tugoer/config"
	"sync"
	"gitee.com/tugoer/orivil"
	"strings"
	"fmt"
)

// 根据域名前缀获得 公众号 配置信息
func GetAppEnv(ctx *orivil.Context) *Env {
	if env, ok := ctx.Session().MGet("wechat-app-env").(*Env); ok {
		return env
	} else {
		env := EnvContainer.GetByHost(ctx.Host)
		ctx.Session().MSet("wechat-app-env", env)
		return env
	}
}

// 所有公众号配置
var EnvContainer = newEnvContainer()

type envContainer struct {
	Namespaces Namespaces
	MainOrigin string
	BaseHost string // 基础域名
	locker    sync.Mutex
	parser *config.Parser
}

type Namespaces map[string]*Env

// 获取 app 配置，originID 为空时默认取得基础配置
func (e *envContainer) Get(originID string) *Env {
	if originID == "" {
		originID = e.MainOrigin
	}
	e.locker.Lock()
	defer e.locker.Unlock()
	return e.Namespaces[originID]
}

// 根据 host 前缀获得 公众号 配置信息, 如果没找到, 则返回主 公众号 配置
func (e *envContainer) GetByHost(host string) *Env {
	prefix := host[:strings.Index(host, ".")]
	e.locker.Lock()
	defer e.locker.Unlock()
	for _, env := range e.Namespaces{
		if env.HostPrefix == prefix {
			return env
		}
	}
	return e.Namespaces[e.MainOrigin]
}

// 保存 公众号 配置
func (e *envContainer) Save(originID string, src *Env) error {
	e.locker.Lock()
	defer e.locker.Unlock()
	for _, env := range e.Namespaces {
		if env.HostPrefix == src.HostPrefix && env.OriginID != originID {
			return fmt.Errorf("域名前缀: %s 已经被注册了", src.HostPrefix)
		}
	}
	e.Namespaces[originID] = src
	err := e.parser.Create("namespaces", e.Namespaces)
	if err != nil {
		return err
	}
	return nil
}

func newEnvContainer() *envContainer {
	e := &envContainer{
		Namespaces: Namespaces{
			"origin-id": &Env{},
		},
		parser: config.NewJsonParser("configs/wechat"),
	}
	err := e.parser.ReadOrCreate("apps", e)
	if err != nil {
		panic(err)
	}
	return e
}

type Env struct {
	Name     string // 公众号名称
	OriginID string // 公众号原始 id
	AppID    string
	Secret   string
	HostPrefix string // 域名前缀

	MchID   string // 商户号
	ShopKey string // 商户密钥
}

// 获得当前公众号主域名
func (e *Env) Host() string {
	return "http://" + e.HostPrefix + "." + EnvContainer.BaseHost
}
